package com.xyy.saas.payment.adpater.fumin.encrypt;

import com.xyy.saas.payment.adpater.fumin.config.CertConstants;
import com.xyy.saas.payment.adpater.fumin.util.CertFileUtil;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.security.Signature;

/**
 * @author tangjunmao
 * @date 2018/10/22
 */
public class RSAEncryptor implements Encryptor {
    /** sha算法 */
    private static final String ALGORITHM_SHA = "SHA256withRSA";

    /**
     * 用公钥对指定字符串加密
     *
     * @param str 需要加密的字符串
     * @param publicKey 公钥字符串
     */
    @Override
    public String encrypt(String str, String publicKey) throws Exception {
        PublicKey key = CertFileUtil.toPublicKey(publicKey);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(CertConstants.ALGORITHM_RSA);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
    }

    /**
     * 用私钥对字符串进行解密
     *
     * @param str 需要解密的字符串
     * @param privateKey 私钥字符串
     */
    @Override
    public String decrypt(String str, String privateKey) throws Exception {
        // 对数据解密
        Cipher cipher = Cipher.getInstance(CertConstants.ALGORITHM_RSA);
        cipher.init(Cipher.DECRYPT_MODE, CertFileUtil.toPrivateKey(privateKey));
        return new String(cipher.doFinal(Base64.decodeBase64(str)), StandardCharsets.UTF_8);
    }

    /**
     * 用私钥对指定字符串进行签名
     *
     * @param str 需要签名的字符串
     */
    @Override
    public String signature(String str) throws Exception {
        return CertFileUtil.detachSign(str.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 用公钥对签名进行验证
     *
     * @param str 需要签名验证的字符串
     * @param signature 签名值
     * @param publicKey 公钥字符串
     */
    @Override
    public boolean verifySignature(String str, String signature, String publicKey) throws Exception {
        // 取公钥匙对象
        PublicKey pubKey = CertFileUtil.toPublicKey(publicKey);
        Signature sign = Signature.getInstance(ALGORITHM_SHA);
        sign.initVerify(pubKey);
        sign.update(str.getBytes(StandardCharsets.UTF_8));
        // 验证签名是否正常
        return sign.verify(Base64.decodeBase64(signature));
    }

}
